package com.spsoft.dmzeinvoice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.reflect.TypeToken;
import com.spsoft.core.constants.CommonConstants;
import com.spsoft.core.model.Result;
import com.spsoft.core.model.leqidmz.param.*;
import com.spsoft.core.model.leqidmz.response.*;
import com.spsoft.dmzeinvoice.common.enums.LeqiAbilityEnum;
import com.spsoft.dmzeinvoice.common.enums.LeqiApiEnum;
import com.spsoft.dmzeinvoice.common.enums.TdysEnum;
import com.spsoft.dmzeinvoice.common.utils.LeqiMockUtil;
import com.spsoft.dmzeinvoice.common.utils.LeqiResultUtil;
import com.spsoft.dmzeinvoice.common.utils.RestTemplateUtil;
import com.spsoft.dmzeinvoice.model.vo.LeqiResult;
import com.spsoft.dmzeinvoice.service.VmsBaseInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.lang.reflect.Type;

@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings({"unchecked"})
public class VmsBaseInfoServiceImpl implements VmsBaseInfoService {

    private final RestTemplateUtil restTemplateUtil;

    // 是否返回模拟数据
    @Value("${leqi.mockFlag}")
    private boolean mockFlag;

    // 调用乐企的请求地址
    @Value("${leqi.url}")
    private String url;

    // 乐企接入单位平台编号
    @Value("${leqi.jrdwptbh}")
    private String jrdwptbh;

    // 乐企沙箱测试标志
    @Value("${leqi.sxcsbz:}")
    private String sxcsbz;

    /**
     * 查询纳税人企业基本信息
     * @param params 请求参数-纳税人识别号
     * @return 纳税人企业基本信息
     */
    @Override
    public Result<QueryEnterpriseInfoVO> queryEnterprise(BaseNsrRequestParams params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.CXNSRJBXX);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getEnterpriseStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        log.info("查询纳税人基本信息返回：{}", responseStr);

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryEnterpriseInfoVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryEnterpriseInfoVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 查询纳税人风险信息
     * @param params 请求参数-纳税人识别号
     * @return 纳税人风险信息
     */
    @Override
    public Result<QueryEnterpriseInfoRiskVO> queryEnterpriseRisk(BaseNsrRequestParams params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.CXNSRFXXX);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getEnterpriseRiskStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryEnterpriseInfoRiskVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryEnterpriseInfoRiskVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 查询纳税人税收分类编码信息
     * @param params 查询税收分类编码参数实体
     * @return 税收分类编码信息
     */
    @Override
    public Result<QueryClassifyCodeVO> queryClassifyCode(QueryClassifyCodeParams params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.CXSSFLBM);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getClassifyCodeStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryClassifyCodeVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryClassifyCodeVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 查询可用税率
     * @param params 请求参数-纳税人识别号
     * @return 查询可用税率
     */
    @Override
    public Result<QueryAvalibleTaxRateVo> queryAvalibleTaxRate(BaseNsrRequestParams params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.CXKYSL);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getAvalibleTaxRateStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryAvalibleTaxRateVo resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryAvalibleTaxRateVo.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 查询授信额度
     * @param params 请求参数-纳税人识别号
     * @return 查询授信额度
     */
    @Override
    public Result<QueryCreditlimitVO> queryCreditLimit(BaseNsrRequestParams params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.CXSXED);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getCreditLimitStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryCreditlimitVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryCreditlimitVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 调整授信额度有效期
     * @param params 请求参数-纳税人识别号
     * @return 调整授信额度有效期
     */
    @Override
    public Result<QueryCreditPeriodVO> queryCreditPeriod(QueryCreditPeriodParams params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.TZSXEDYXQ);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getCreditPeriodStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryCreditPeriodVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryCreditPeriodVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 下载/退回授信额度
     * @param params 请求参数-纳税人识别号
     * @return 调整授信额度有效期
     */
    @Override
    public Result<ApplyCreditVO> applyCredit(ApplyCreditParams params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.XZTHSXED);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getApplyCreditStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        ApplyCreditVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), ApplyCreditVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 获取数电票批量预赋码信息
     * @param params 请求参数-获取数电票批量预赋码信息对象
     * @return 预赋码信息
     */
    @Override
    public Result<AssignedCodeResponseVO> assignedCode(AssignedCodeParams params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.QDFPPLFM);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getAssignedCodeStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        AssignedCodeResponseVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), AssignedCodeResponseVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 查询差额征税编码信息
     * @param params 请求参数
     * @return 差额征税编码信息
     */
    @Override
    public Result<QueryDifferentialTaxationVO> differential(BaseUserInfoParam params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.CXCEZSBM);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getDifferentialTaxationStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryDifferentialTaxationVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryDifferentialTaxationVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    @Override
    public Result<QueryHouseInfoVO> queryHouseInfo(QueryHouseInfoParams params) {
        // 组装请求头
        LeqiHeader leqiHeader = buildHeader(params, LeqiApiEnum.CXFYXX);

        String responseStr;
        String requestJson = JSONObject.toJSONString(params);

        if (mockFlag) {
            // Mock数据
            responseStr = LeqiMockUtil.getHouseInfoStr();
        } else {
            // 调乐企接口
            responseStr = restTemplateUtil.postLeQi(leqiHeader, requestJson);
        }

        Type type = new TypeToken<LeqiResult<String>>(){}.getType();
        LeqiResult<String> leqiResult = LeqiResultUtil.jsonToLeqiResult(responseStr, type);
        LeqiResult.ErrorInfo errorInfo = leqiResult.getResponse().getError();
        // 有error节点，返回error
        if (errorInfo != null) {
            return Result.ERRORT(errorInfo.getCode(), errorInfo.getMessage());
        }
        QueryHouseInfoVO resultVo = JSONObject.parseObject(leqiResult.getResponse().getData(), QueryHouseInfoVO.class);
        // 业务层不为00，返回error
        if (!CommonConstants.LEQI_SUCCESS.equals(resultVo.getReturncode())) {
            return Result.ERRORT(resultVo.getReturncode(), resultVo.getReturnmsg());
        }

        return Result.OK(resultVo);
    }

    /**
     * 构建乐企请求头信息
     * @param params 入参
     * @param leqiApiEnum 乐企服务编码枚举
     */
    private LeqiHeader buildHeader(BaseUserInfoParam params, LeqiApiEnum leqiApiEnum) {
        LeqiHeader leqiHeader = new LeqiHeader();
        LeqiAbilityEnum leqiAbility;
        if (TdysEnum.TDYS_05.getCode().equals(params.getTdys())) {
            leqiAbility = LeqiAbilityEnum.BDCXS;
        } else if (TdysEnum.TDYS_06.getCode().equals(params.getTdys())) {
            leqiAbility = LeqiAbilityEnum.BDCZL;
        } else if (TdysEnum.TDYS_09.getCode().equals(params.getTdys())) {
            leqiAbility = LeqiAbilityEnum.LKYS;
        } else {
            leqiAbility = LeqiAbilityEnum.BASE;
        }

        leqiHeader.setJrdwptbh(jrdwptbh);
        leqiHeader.setSydwptbh(params.getSydwptbh());
        leqiHeader.setFwbm(leqiApiEnum.getApiCode());
        leqiHeader.setNlbm(leqiAbility.getAbilityCode());
        leqiHeader.setYlbm(leqiAbility.getUseCasesCode());
        leqiHeader.setRequestUrl(url + leqiAbility.getAbilityCode() + "/" + leqiApiEnum.getApiCode() + "/");
        // 仅适用于能力开通后或能力审核中时进行沙箱调用，能力未提交审核前不要加上此参数
        if (StringUtils.isNotBlank(sxcsbz)) {
            leqiHeader.setSxcsbz(sxcsbz);
        }

        return leqiHeader;
    }

}
